/*
******************************** Header Files
*/

#include	"MacTCPCommonTypes.h"
#include	"TCPPB.h"
#include	"AddressXlation.h"
#include	"GetMyIPAddr.h"

/*
******************************** Global IPP Driver Reference Number
*/

short		gIPPDriverRefNum;

/*
******************************** PBControl Interface Prototypes
*/

OSErr _TCPInit			(void);
OSErr _TCPGetIP			(struct IPParamBlock *pb, ip_addr *ip, long *netMask, ProcPtr ioCompletion, Boolean async);
OSErr _TCPCreate		(TCPiopb *pb, StreamPtr *stream, Ptr rcvBufPtr, long rcvBufLen, TCPNotifyProc aNotifyProc, Ptr userDataPtr, TCPIOCompletionProc ioCompletion, Boolean async);
OSErr _TCPPassiveOpen	(TCPiopb *pb, StreamPtr stream, ip_addr *remoteIP, tcp_port *remotePort, ip_addr *localIP, tcp_port *localPort, Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async);
OSErr _TCPActiveOpen	(TCPiopb *pb, StreamPtr stream, ip_addr remoteIP, tcp_port remotePort, ip_addr *localIP, tcp_port *localPort, Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async);
OSErr _TCPSend			(TCPiopb *pb, StreamPtr stream, wdsEntry *wdsPtr, Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async);
OSErr _TCPNoCopyRcv		(TCPiopb *pb, StreamPtr stream, rdsEntry *rdsPtr, unsigned short rdsLength, Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async);
OSErr _TCPRcv			(TCPiopb *pb, StreamPtr stream, Ptr rcvBufPtr, unsigned short *rcvBufLen, Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async);
OSErr _TCPBfrReturn		(TCPiopb *pb, StreamPtr stream, Ptr rdsPtr, Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async);
OSErr _TCPClose			(TCPiopb *pb, StreamPtr stream, Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async);
OSErr _TCPAbort			(TCPiopb *pb, StreamPtr stream, Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async);
OSErr _TCPStatus		(TCPiopb *pb, StreamPtr stream, struct TCPStatusPB *status, Ptr userData, TCPIOCompletionProc ioCompletion, Boolean async);
OSErr _TCPRelease		(TCPiopb *pb, StreamPtr stream, Ptr *rcvBufPtr, long *rcvBufLen, TCPIOCompletionProc ioCompletion, Boolean async);

/*
******************************** PBControl Interface Procedures
*/

#pragma segment TCPPB

OSErr	_TCPInit()
{

	auto	ParamBlockRec		pb;
	auto	OSErr				osErr;
		
	pb.ioParam.ioCompletion		= 0; 
	pb.ioParam.ioNamePtr		= "\p.ipp"; 
	pb.ioParam.ioPermssn		= fsCurPerm;
	
	osErr = PBOpen(&pb, false);
	if (noErr == osErr) {
		gIPPDriverRefNum		= pb.ioParam.ioRefNum;
	}
		
	return osErr;
}

OSErr	_TCPGetIP(pb, ip, netMask, ioCompletion, async)
			struct IPParamBlock		*pb;
			ip_addr					*ip;
			long					*netMask;
			ProcPtr					ioCompletion;
			Boolean					async;
{

	auto	OSErr					osErr;
	
	pb->ioCompletion				= ioCompletion;
	pb->ioCRefNum					= gIPPDriverRefNum;
	pb->csCode						= ipctlGetAddr;
		
	osErr = PBControl((ParmBlkPtr) pb, async);
	if (!async && (noErr == osErr)) {
		*ip							= pb->ourAddress;
		*netMask					= pb->ourNetMask;
	}
		
	return osErr;
}


OSErr	_TCPCreate(pb, stream, rcvBufPtr, rcvBufLen, aNotifyProc, userDataPtr, ioCompletion, async)
			TCPiopb					*pb;
			StreamPtr				*stream;
			Ptr						rcvBufPtr;
			long					rcvBufLen;
			TCPNotifyProc			aNotifyProc;
			Ptr						userDataPtr;
			TCPIOCompletionProc		ioCompletion;
			Boolean					async;
{

	auto	OSErr					osErr;
	
	pb->ioCompletion					= ioCompletion;
	pb->ioCRefNum						= gIPPDriverRefNum;
	pb->csCode							= TCPCreate;
	
	pb->csParam.create.rcvBuff			= rcvBufPtr;	
	pb->csParam.create.rcvBuffLen		= rcvBufLen;	
	pb->csParam.create.notifyProc		= aNotifyProc;
	pb->csParam.create.userDataPtr		= userDataPtr;
	
	osErr = PBControl((ParmBlkPtr) pb, async);
	if (!async && (noErr == osErr)) {
		*stream							= pb->tcpStream;
	}
		
	return osErr;
}


OSErr _TCPPassiveOpen (pb, stream, remoteIP, remotePort, localIP, localPort, userData, ioCompletion, async)
			TCPiopb					*pb;
			StreamPtr				stream;
			ip_addr					*remoteIP; 
			tcp_port				*remotePort; 
			ip_addr					*localIP; 
			tcp_port				*localPort;
			Ptr						userData;
			TCPIOCompletionProc		ioCompletion;
			Boolean					async;
{

	auto	OSErr					osErr;
	auto	short					index;
	
	pb->ioCompletion						= ioCompletion;
	pb->ioCRefNum							= gIPPDriverRefNum;
	pb->csCode								= TCPPassiveOpen;
	pb->tcpStream							= stream;
	
	pb->csParam.open.ulpTimeoutValue		= 0;	
	pb->csParam.open.ulpTimeoutAction		= 0;	
	pb->csParam.open.validityFlags			= 0;	
	pb->csParam.open.commandTimeoutValue	= 0;	
	pb->csParam.open.remoteHost				= *remoteIP;	
	pb->csParam.open.remotePort				= *remotePort;	
	pb->csParam.open.localHost				= 0;	
	pb->csParam.open.localPort				= *localPort;	
	pb->csParam.open.tosFlags				= 0;	
	pb->csParam.open.precedence				= 0;	
	pb->csParam.open.dontFrag				= 0;	
	pb->csParam.open.timeToLive				= 0;
	pb->csParam.open.security				= 0;	
	pb->csParam.open.optionCnt				= 0;
	for (index = 0; index < sizeof(pb->csParam.open.options); ++index)	
		pb->csParam.open.options[index]		= 0;	
	pb->csParam.open.userDataPtr			= userData;
	
	osErr = PBControl((ParmBlkPtr) pb, async);
	if (!async && (noErr == osErr)) {
		*remoteIP							= pb->csParam.open.remoteHost;	
		*remotePort							= pb->csParam.open.remotePort;	
		*localIP							= pb->csParam.open.localHost;	
		*localPort							= pb->csParam.open.localPort;
	}

	return osErr;
}


OSErr _TCPActiveOpen (pb, stream, remoteIP, remotePort, localIP, localPort, userData, ioCompletion, async)
			TCPiopb					*pb;
			StreamPtr				stream;
			ip_addr					remoteIP; 
			tcp_port				remotePort; 
			ip_addr					*localIP; 
			tcp_port				*localPort;
			Ptr						userData;
			TCPIOCompletionProc		ioCompletion;
			Boolean					async;
{

	auto	OSErr					osErr;
	auto	short					index;
	
	pb->ioCompletion						= ioCompletion;
	pb->ioCRefNum							= gIPPDriverRefNum;
	pb->csCode								= TCPActiveOpen;
	pb->tcpStream							= stream;
	
	pb->csParam.open.ulpTimeoutValue		= 0;
	pb->csParam.open.ulpTimeoutAction		= 0;
	pb->csParam.open.validityFlags			= 0;	
	pb->csParam.open.commandTimeoutValue	= 0;	
	pb->csParam.open.remoteHost				= remoteIP;	
	pb->csParam.open.remotePort				= remotePort;	
	pb->csParam.open.localHost				= 0;	
	pb->csParam.open.localPort				= *localPort;	
	pb->csParam.open.tosFlags				= 0;	
	pb->csParam.open.precedence				= 0;	
	pb->csParam.open.dontFrag				= 0;	
	pb->csParam.open.timeToLive				= 0;
	pb->csParam.open.security				= 0;	
	pb->csParam.open.optionCnt				= 0;
	for (index = 0; index < sizeof(pb->csParam.open.options); ++index)	
		pb->csParam.open.options[index]		= 0;	
	pb->csParam.open.userDataPtr			= userData;
	
	osErr = PBControl((ParmBlkPtr) pb, async);
	if (!async && (noErr == osErr)) {
		*localIP							= pb->csParam.open.localHost;	
		*localPort							= pb->csParam.open.localPort;
	}

	return osErr;
}


OSErr _TCPSend (pb, stream, wdsPtr, userData, ioCompletion, async)
			TCPiopb					*pb;
			StreamPtr				stream;
			wdsEntry 				*wdsPtr;
			Ptr						userData;
			TCPIOCompletionProc		ioCompletion;
			Boolean					async;
{

	auto	OSErr					osErr;
	
	pb->ioCompletion					= ioCompletion;
	pb->ioCRefNum						= gIPPDriverRefNum;
	pb->csCode							= TCPSend;
	pb->tcpStream						= stream;
	
	pb->csParam.send.ulpTimeoutValue	= 0;	
	pb->csParam.send.ulpTimeoutAction	= 0;	
	pb->csParam.send.validityFlags		= 0;	
	pb->csParam.send.pushFlag			= 0;	
	pb->csParam.send.urgentFlag			= 0;	
	pb->csParam.send.wdsPtr				= (Ptr) wdsPtr;	
	pb->csParam.send.sendFree			= 0;	
	pb->csParam.send.sendLength			= 0;	
	pb->csParam.send.userDataPtr		= userData;
	
	osErr = PBControl((ParmBlkPtr) pb, async);

	return osErr;
}


OSErr _TCPNoCopyRcv (pb, stream, rdsPtr, rdsLength, userData, ioCompletion, async)
			TCPiopb					*pb;
			StreamPtr				stream;
			rdsEntry				*rdsPtr;
			unsigned short			rdsLength;
			Ptr						userData;
			TCPIOCompletionProc		ioCompletion;
			Boolean					async;
{

	auto	OSErr					osErr;
	
	pb->ioCompletion							= ioCompletion;
	pb->ioCRefNum								= gIPPDriverRefNum;
	pb->csCode									= TCPNoCopyRcv;
	pb->tcpStream								= stream;
	
	pb->csParam.receive.commandTimeoutValue		= 0;	
	pb->csParam.receive.urgentFlag				= 0;	
	pb->csParam.receive.markFlag				= 0;	
	pb->csParam.receive.rdsPtr					= (Ptr) rdsPtr;	
	pb->csParam.receive.rdsLength				= rdsLength;	
	pb->csParam.receive.userDataPtr				= userData;
	
	osErr = PBControl((ParmBlkPtr) pb, async);

	return osErr;
}


OSErr _TCPRcv (pb, stream, rcvBufPtr, rcvBufLen, userData, ioCompletion, async)
			TCPiopb					*pb;
			StreamPtr				stream;
			Ptr						rcvBufPtr;
			unsigned short			*rcvBufLen;
			Ptr						userData;
			TCPIOCompletionProc		ioCompletion;
			Boolean					async;
{

	auto	OSErr					osErr;
	
	pb->ioCompletion							= ioCompletion;
	pb->ioCRefNum								= gIPPDriverRefNum;
	pb->csCode									= TCPRcv;
	pb->tcpStream								= stream;
	
	pb->csParam.receive.commandTimeoutValue		= 0;	
	pb->csParam.receive.urgentFlag				= 0;	
	pb->csParam.receive.markFlag				= 0;	
	pb->csParam.receive.rcvBuff					= rcvBufPtr;	
	pb->csParam.receive.rcvBuffLen				= *rcvBufLen;	
	pb->csParam.receive.userDataPtr				= userData;
	
	osErr = PBControl((ParmBlkPtr) pb, async);
	if (! async)
		*rcvBufLen = pb->csParam.receive.rcvBuffLen;

	return osErr;
}


OSErr _TCPBfrReturn (pb, stream, rdsPtr, userData, ioCompletion, async)
			TCPiopb					*pb;
			StreamPtr				stream;
			Ptr						rdsPtr;
			Ptr						userData;
			TCPIOCompletionProc		ioCompletion;
			Boolean					async;
{

	auto	OSErr					osErr;
	
	pb->ioCompletion					= ioCompletion;
	pb->ioCRefNum						= gIPPDriverRefNum;
	pb->csCode							= TCPRcvBfrReturn;
	pb->tcpStream						= stream;
	
	pb->csParam.receive.rdsPtr			= rdsPtr;	
	pb->csParam.receive.userDataPtr		= userData;
	
	osErr = PBControl((ParmBlkPtr) pb, async);

	return osErr;
}


OSErr _TCPClose (pb, stream, userData, ioCompletion, async)
			TCPiopb					*pb;
			StreamPtr				stream;
			Ptr						userData;
			TCPIOCompletionProc		ioCompletion;
			Boolean					async;
{

	auto	OSErr					osErr;
	
	pb->ioCompletion					= ioCompletion;
	pb->ioCRefNum						= gIPPDriverRefNum;
	pb->csCode							= TCPClose;
	pb->tcpStream						= stream;
	
	pb->csParam.close.ulpTimeoutValue	= 0;	
	pb->csParam.close.ulpTimeoutAction	= 0;	
	pb->csParam.close.validityFlags		= 0;	
	pb->csParam.close.userDataPtr		= userData;
	
	osErr = PBControl((ParmBlkPtr) pb, async);

	return osErr;
}


OSErr _TCPAbort (pb, stream, userData, ioCompletion, async)
			TCPiopb					*pb;
			StreamPtr				stream;
			Ptr						userData;
			TCPIOCompletionProc		ioCompletion;
			Boolean					async;
{

	auto	OSErr					osErr;
	
	pb->ioCompletion					= ioCompletion;
	pb->ioCRefNum						= gIPPDriverRefNum;
	pb->csCode							= TCPAbort;
	pb->tcpStream						= stream;
	
	pb->csParam.abort.userDataPtr		= userData;
	
	osErr = PBControl((ParmBlkPtr) pb, async);

	return osErr;
}


OSErr _TCPStatus (pb, stream, status, userData, ioCompletion, async)
			TCPiopb					*pb;
			StreamPtr				stream;
			struct TCPStatusPB		*status;
			Ptr						userData;
			TCPIOCompletionProc		ioCompletion;
			Boolean					async;
{

	auto	OSErr					osErr;
	
	pb->ioCompletion					= ioCompletion;
	pb->ioCRefNum						= gIPPDriverRefNum;
	pb->csCode							= TCPStatus;
	pb->tcpStream						= stream;
	
	pb->csParam.status.userDataPtr		= userData;
	
	osErr = PBControl((ParmBlkPtr) pb, async);
	if (!async && (noErr == osErr)) {
		*status							= pb->csParam.status;	
	}

	return osErr;
}


OSErr _TCPRelease (pb, stream, rcvBufPtr, rcvBufLen, ioCompletion, async)
			TCPiopb					*pb;
			StreamPtr				stream;
			Ptr						*rcvBufPtr;
			long					*rcvBufLen;
			TCPIOCompletionProc		ioCompletion;
			Boolean					async;
{

	auto	OSErr					osErr;
	
	pb->ioCompletion					= ioCompletion;
	pb->ioCRefNum						= gIPPDriverRefNum;
	pb->csCode							= TCPRelease;
	pb->tcpStream						= stream;
	
	osErr = PBControl((ParmBlkPtr) pb, async);
	if (!async && (noErr == osErr)) {
		*rcvBufPtr						= pb->csParam.create.rcvBuff;	
		*rcvBufLen						= pb->csParam.create.rcvBuffLen;	
	}

	return osErr;
}

